{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e2376f66",
   "metadata": {},
   "source": [
    "[Official documentation on chat from LangChain](https://python.langchain.com/en/latest/modules/models/chat/getting_started.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "dccede54",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain import LLMChain\n",
    "from langchain import PromptTemplate\n",
    "from langchain.prompts.chat import (\n",
    "    ChatPromptTemplate,\n",
    "    SystemMessagePromptTemplate,\n",
    "    AIMessagePromptTemplate,\n",
    "    HumanMessagePromptTemplate,\n",
    ")\n",
    "from langchain.schema import (\n",
    "    AIMessage,\n",
    "    HumanMessage,\n",
    "    SystemMessage\n",
    ")\n",
    "\n",
    "\n",
    "# Supporting libraries\n",
    "import os\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "af154051",
   "metadata": {
    "hide_input": false
   },
   "outputs": [],
   "source": [
    "OPENAI_API_KEY = os.getenv('OPENAI_API_KEY', 'YourAPIKeyIfNotSet')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9dc0f73e",
   "metadata": {},
   "source": [
    "### 0. Simple Input/Output Still works\n",
    "\n",
    "You just need to pass it as a message instead. More on this in a second."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "24231b46",
   "metadata": {},
   "outputs": [],
   "source": [
    "chat = ChatOpenAI(openai_api_key=OPENAI_API_KEY)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2a68def1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='\\n\\nCalifornia.', additional_kwargs={})"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "message = [HumanMessage(content=\"What is the name of the most populous state in the USA?\")]\n",
    "\n",
    "chat(message)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7409e722",
   "metadata": {},
   "source": [
    "### 1. Chat Messages\n",
    "\n",
    "* HumanMessage: A message sent from the perspective of the human\n",
    "* AIMessage: A message sent from the perspective of the AI the human is interacting with\n",
    "* SystemMessage: A message setting the objectives the AI should follow\n",
    "* ChatMessage: A message allowing for arbitrary setting of role. You won’t be using this too much"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "dd3e4528",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='I hate programming.', additional_kwargs={})"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "messages = [\n",
    "    SystemMessage(content=\"Say the opposite of what the user says\"),\n",
    "    HumanMessage(content=\"I love programming.\")\n",
    "]\n",
    "chat(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4b4d207f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='The moon is not out.', additional_kwargs={})"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "messages = [\n",
    "    SystemMessage(content=\"Say the opposite of what the user says\"),\n",
    "    HumanMessage(content=\"I love programming.\"),\n",
    "    AIMessage(content='I hate programming.'),\n",
    "    HumanMessage(content=\"The moon is out\")\n",
    "]\n",
    "chat(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b6ba38cf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='You said, \"I love programming.\"', additional_kwargs={})"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "messages = [\n",
    "    SystemMessage(content=\"Say the opposite of what the user says\"),\n",
    "    HumanMessage(content=\"I love programming.\"),\n",
    "    AIMessage(content='I hate programming.'),\n",
    "    HumanMessage(content=\"What is the first thing that I said?\")\n",
    "]\n",
    "chat(messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "baf305b3",
   "metadata": {},
   "source": [
    "#### Batch Messages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "2e2b3636",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LLMResult(generations=[[ChatGeneration(text='Amazingly appetizing apples.', generation_info=None, message=AIMessage(content='Amazingly appetizing apples.', additional_kwargs={}))], [ChatGeneration(text='Dangerous dogs do demand due diligence.', generation_info=None, message=AIMessage(content='Dangerous dogs do demand due diligence.', additional_kwargs={}))]], llm_output=None)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "batch_messages = [\n",
    "    [\n",
    "        SystemMessage(content=\"You are a helpful word machine that creates an alliteration using a base word\"),\n",
    "        HumanMessage(content=\"Base word: Apple\")\n",
    "    ],\n",
    "    [\n",
    "        SystemMessage(content=\"You are a helpful word machine that creates an alliteration using a base word\"),\n",
    "        HumanMessage(content=\"Base word: Dog\")\n",
    "    ],\n",
    "]\n",
    "chat.generate(batch_messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3600f53",
   "metadata": {},
   "source": [
    "### Prompt Templates\n",
    "With one or more `MessagePromptTemplates` you can build a `ChatPromptTemplate`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ddf3c969",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Make SystemMessagePromptTemplate\n",
    "prompt=PromptTemplate(\n",
    "    template=\"Propose creative ways to incorporate {food_1} and {food_2} in the cuisine of the users choice.\",\n",
    "    input_variables=[\"food_1\", \"food_2\"]\n",
    ")\n",
    "\n",
    "system_message_prompt = SystemMessagePromptTemplate(prompt=prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "401f2bd4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "SystemMessage(content='Propose creative ways to incorportate Bacon and Shrimp in the cuisine of the users choice.', additional_kwargs={})"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Output of system_message_prompt\n",
    "system_message_prompt.format(food_1=\"Bacon\", food_2=\"Shrimp\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a2c9e821",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Make HumanMessagePromptTemplate\n",
    "human_template=\"{text}\"\n",
    "human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1947bf3a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptTemplate(input_variables=['food_1', 'food_2', 'text'], output_parser=None, partial_variables={}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=['food_1', 'food_2'], output_parser=None, partial_variables={}, template='Propose creative ways to incorportate {food_1} and {food_2} in the cuisine of the users choice.', template_format='f-string', validate_template=True), additional_kwargs={}), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['text'], output_parser=None, partial_variables={}, template='{text}', template_format='f-string', validate_template=True), additional_kwargs={})])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create ChatPromptTemplate: Combine System + Human\n",
    "chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])\n",
    "chat_prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "e97284de",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[SystemMessage(content='Propose creative ways to incorportate Bacon and Shrimp in the cuisine of the users choice.', additional_kwargs={}),\n",
       " HumanMessage(content='I really like food from Germany.', additional_kwargs={})]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat_prompt_with_values = chat_prompt.format_prompt(food_1=\"Bacon\", \\\n",
    "                                                   food_2=\"Shrimp\", \\\n",
    "                                                   text=\"I really like food from Germany.\")\n",
    "\n",
    "chat_prompt_with_values.to_messages()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "c0de4582",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Great choice! Here are some creative ways to incorporate bacon and shrimp into German cuisine:\n",
      "\n",
      "1. Bacon-wrapped shrimp skewers: Marinate shrimp in a mixture of olive oil, garlic, paprika, and cayenne pepper. Wrap each shrimp with a thin slice of bacon and thread onto skewers. Grill over medium heat until the bacon is crispy and the shrimp is pink and cooked through. Serve with a side of mustard for dipping.\n",
      "\n",
      "2. German shrimp and bacon soup: Start by cooking diced bacon until crispy in a large pot. Remove the bacon and set it aside. Add diced onion, celery, and carrots to the bacon fat and cook until softened. Add chicken or vegetable broth, diced potatoes, and diced cooked shrimp to the pot. Simmer until the potatoes are tender. Serve hot with a sprinkle of crispy bacon on top.\n",
      "\n",
      "3. Bacon and shrimp sauerkraut: Sauté diced bacon and sliced onions in a skillet until the onions are caramelized. Add sauerkraut, apple cider vinegar, and a little bit of sugar to the pan. Cook until the sauerkraut is tender and the liquid has reduced. Stir in cooked shrimp and reheat briefly. Serve as a side dish with a German-style sausage.\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "response = chat(chat_prompt_with_values.to_messages()).content\n",
    "print (response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20a756b5",
   "metadata": {},
   "source": [
    "#### With Streaming"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "aac2d6f7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Great choice! Here are some creative ways to incorporate bacon and shrimp into German cuisine:\n",
      "\n",
      "1. Bacon and Shrimp Spätzle: Spätzle is a traditional German egg noodle dish. Add cooked shrimp and crispy bacon to the spätzle and toss with butter and fresh herbs for a delicious and hearty meal.\n",
      "\n",
      "2. Shrimp and Bacon Sauerkraut: Add cooked shrimp and crispy bacon to sauerkraut for a flavorful and protein-packed side dish. Serve alongside traditional German sausages or pork dishes.\n",
      "\n",
      "3. Bacon and Shrimp Potato Salad: German potato salad is typically made with bacon and vinegar dressing. Add cooked shrimp to the salad for a unique twist on this classic dish.\n",
      "\n",
      "4. Shrimp and Bacon Schnitzel: Top a traditional German schnitzel with cooked shrimp and crispy bacon for a decadent and flavorful meal.\n",
      "\n",
      "5. Bacon and Shrimp Bratwurst: Mix cooked shrimp and crispy bacon into the bratwurst mixture before grilling for a unique and delicious twist on this classic German sausage.\n",
      "\n",
      "Enjoy experimenting with these creative ways to incorporate bacon and shrimp into your favorite German dishes!"
     ]
    }
   ],
   "source": [
    "from langchain.callbacks.manager import CallbackManager\n",
    "from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
    "chat = ChatOpenAI(openai_api_key=OPENAI_API_KEY, streaming=True, callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]), verbose=True, temperature=0)\n",
    "\n",
    "resp = chat(chat_prompt_with_values.to_messages())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d771a133",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
